/*
 * functions.c
 *
 *  Created on: 2011-11-25
 *      Author: xugp
 */
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <event.h>
#include <time.h>
#include "gameserver.h"
#include "list.h"
#include "hashtable.h"
#include "functions.h"
#include "utils.h"
#include "goldgame.h"

struct __game_t;

typedef struct __room_t {
	int roomid;
	char roomname[48];
	list_t * gamelist;
	list_t * userlist;
} room_t;

typedef struct __user_t{
	char username[48];
	room_t * room;
	struct __game_t * game;
	connection_t * pconn;
} user_t;

typedef struct __gameuser_t{
	user_t * user;
	int ready;
} gameuser_t;

#define MAX_USER_COUNT 10

typedef struct __game_t {
	char gameid[48];
	char gamename[48];

	gameuser_t * gameusers[MAX_USER_COUNT];

	int state;  //0,1
	int maxusercount;//当前类型游戏最多玩家
} game_t;





hashtable_t * usertable;
pthread_mutex_t usertablelock;
room_t roomlist[100];


//extern hashtable_t * connectiontable;
//extern list_t * connectionlist;
//extern list_t *requestlist;

extern int totalconncount;
extern int totalrequestcount;


void init(){
	usertable=create_hashtable(50000);
	pthread_mutex_init(&usertablelock,PTHREAD_MUTEX_TIMED_NP);
	int i;
	for(i=0;i<100;i++){
		room_t * room=&roomlist[i];
		room->roomid=i;
		sprintf(room->roomname,"room-%d",i);
		room->gamelist=list_create();
		room->userlist=list_create();
	}
}

room_t * findroom(int roomid){
  return &(roomlist[roomid]);
}

void exitgame(user_t * user){
	game_t * game=user->game;
	int i,n=0;
	if(game!=NULL){
		for(i=0;i<game->maxusercount;i++){
			gameuser_t * gameuser1=game->gameusers[i];
			if(gameuser1!=NULL){
				if(gameuser1->user!=user){
					writecmd(gameuser1->user->pconn,"userexit",user->username);
					n++;
				}else{
					game->gameusers[i]=NULL;
					free(gameuser1);
				}
			}
		}

		user->game=NULL;
		if(n==0){
			list_remove(game,user->room->gamelist);
			free(game);
		}
	}
}

void userexit(user_t * user){
	if(user!=NULL){
		room_t * room=user->room;
		game_t * game=user->game;

		if(game!=NULL){
			exitgame(user);
		}

		if(room!=NULL){
			list_remove(user,room->userlist);
		}
		pthread_mutex_lock(&usertablelock);
		hash_remove(user->username,usertable);
		pthread_mutex_unlock(&usertablelock);
		free(user);
	}
}


void do_login(const request_t * prequest){
	char username[48]={0};
	char roomname[48]={0};
	getparam(username,sizeof(username)-1,1,0,prequest->querystring);
	getparam(roomname,sizeof(roomname)-1,2,0,prequest->querystring);
	int roomid=atoi(roomname);
	room_t * room=findroom(roomid);

	if(room!=NULL){
		pthread_mutex_lock(&usertablelock);
		user_t * user=hash_value(username,usertable);
		pthread_mutex_unlock(&usertablelock);
		if(user==NULL){
			user=malloc(sizeof(user_t));
			memset(user,0,sizeof(user_t));
			strcpy(user->username,username);
			pthread_mutex_lock(&usertablelock);
			hash_insert(username,user,usertable);
			pthread_mutex_unlock(&usertablelock);
		}else{
		}
		user->pconn=prequest->pconn;
		prequest->pconn->user=user;
		user->room=room;
		writecmd(prequest->pconn,"login","%s",username);
	}else{
		writecmd(prequest->pconn,"error","room not found");
	}


}

void do_creategame(const request_t * prequest){
	user_t * myuser=(user_t *)(prequest->pconn->user);
	if(myuser!=NULL){
		if(myuser->room!=NULL){
			game_t * game=malloc(sizeof(game_t));
			memset(game,0,sizeof(game_t));
			game->maxusercount=2;
			gameuser_t * gameuser=malloc(sizeof(gameuser_t));
			gameuser->user=myuser;
			gameuser->ready=0;

			game->gameusers[0]=gameuser;

			strcpy(game->gamename,myuser->username);

			struct timeval tv;
			gettimeofday(&tv,NULL);
			sprintf(game->gameid,"%d-%u",prequest->pconn->fd,(uint)tv.tv_sec);

			list_push_head(game,myuser->room->gamelist);

			myuser->game=game;

			writecmd(prequest->pconn,"creategame","OK");
		}else{
			writecmd(prequest->pconn,"error","not login to the room");
		}

	}else{
		writecmd(prequest->pconn,"error","not login");
	}
}

void do_fetchgamelist(const request_t * prequest){
	user_t * myuser=(user_t *)(prequest->pconn->user);
	char data[1000]={0};
	if(myuser!=NULL && myuser->room!=NULL){
		room_t * room=myuser->room;
		int c=0;
		node_t * node=room->gamelist->head;
		while(node!=NULL){
			game_t * game=(game_t *)(node->data);
			if(game->state==0){
				strcat(data,game->gameid);
				strcat(data,":");
				strcat(data,game->gamename);
				strcat(data,",");
				c++;
			}
			node=node->next;
		}
		if(c>0){
			data[strlen(data)-1]='\0';
		}
		writecmd(prequest->pconn,"gamelist",data);
	}else{

	}
}


void do_joingame(const request_t * prequest){
	char gameid[48]={0};
	getparam(gameid,sizeof(gameid)-1,1,0,prequest->querystring);

	user_t * myuser=(user_t *)(prequest->pconn->user);

	if(myuser!=NULL){
		room_t * room=myuser->room;
		if(room!=NULL){
			game_t * game=NULL;

			node_t * node=room->gamelist->head;
			while(node!=NULL){
				game_t *game1=node->data;
				if(strcmp(game1->gameid,gameid)==0){
					game=game1;
					break;
				}
				node=node->next;
			}

			if(game!=NULL){
				int i;
				int joinposition=-1;
				for(i=0;i<game->maxusercount;i++){
					gameuser_t * gameuser=game->gameusers[i];
					if(gameuser==NULL){
						gameuser=malloc(sizeof(gameuser_t));
						gameuser->user=myuser;
						gameuser->ready=0;
						game->gameusers[i]=gameuser;
						myuser->game=game;
						myuser->room=room;
						joinposition=i;
						break;
					}
				}

				if(joinposition>=0){
					for(i=0;i<game->maxusercount;i++){
						if(game->gameusers[i]!=NULL){
							writecmd(game->gameusers[i]->user->pconn,"joingame","%s %d",myuser->username,joinposition);
						}
					}
				}else{
					writecmd(prequest->pconn,"error","game is full");
				}
			}else{
				writecmd(prequest->pconn,"error","game not found");
			}

		}else{
			writecmd(prequest->pconn,"error","room not found");
		}

	}else{
		writecmd(prequest->pconn,"error","not login");
	}
}

void do_ready(const request_t * prequest){
	int i;
	user_t * myuser=(user_t *)(prequest->pconn->user);
	game_t * game=myuser->game;

	//user_t * user;
	int readycount=0;
	for(i=0;i<game->maxusercount;i++){
		gameuser_t * gameuser=game->gameusers[i];
		if(gameuser!=NULL){
			if(gameuser->user==myuser){
				gameuser->ready=1;
				readycount++;
			}else{
				if(gameuser->ready==1){
					readycount++;
				}
			}
			writecmd(gameuser->user->pconn,"ready","%s",myuser->username);
		}
	}

	if(readycount==game->maxusercount){
		//人都进来了，而且全部准备好了
		//初始化游戏参数，然后通知给用户并且开始游戏
		char data[1000]={0};
		initgolddata(data,1);
		for(i=0;i<game->maxusercount;i++){
			gameuser_t *gameuser1=game->gameusers[i];
			if(gameuser1!=NULL){
				writecmd(gameuser1->user->pconn,"gamestart","%s",data);
			}
		}
		game->state=1;
	}
}

void do_exitgame(const request_t * prequest){
	user_t * user=prequest->pconn->user;
	if(user!=NULL){
		exitgame(user);
	}
}

void do_gameuser(const request_t * prequest){
	user_t * myuser=(user_t *)(prequest->pconn->user);
	game_t * game=myuser->game;
	char users[1000]={0};
	int i;
	for(i=0;i<game->maxusercount;i++){
		gameuser_t * gameuser=game->gameusers[i];
		if(gameuser!=NULL){
			char t[100]={0};
			sprintf(t,"%s,%d,%d;",gameuser->user->username,gameuser->ready,i);
			strcat(users,t);
		}
	}
	if(strlen(users)>0){
		users[strlen(users)-1]='\0';
	}


	writecmd(myuser->pconn,"gameuser","%s",users);
}

void do_gamemsg(const request_t * prequest){
	int i;
	user_t * myuser=(user_t *)(prequest->pconn->user);
	game_t * game=myuser->game;
	for(i=0;i<game->maxusercount;i++){
		gameuser_t * gameuser=game->gameusers[i];
		if(gameuser!=NULL){
			writecmd(gameuser->user->pconn,prequest->querystring,NULL);
		}
	}
}
